package com.yami.shop.mystery.common.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.bean.dto.SkuStockLockDTO;
import com.yami.shop.bean.enums.AirdropRecordEnum;
import com.yami.shop.bean.enums.EsOperationType;
import com.yami.shop.bean.event.EsProductUpdateEvent;
import com.yami.shop.bean.event.MysteryBoxSoldOutEvent;
import com.yami.shop.bean.model.*;
import com.yami.shop.bean.vo.EsProdUpdateVO;
import com.yami.shop.common.bean.PageDTO;
import com.yami.shop.common.bean.PageVO;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.i18n.I18nMessage;
import com.yami.shop.common.response.ResponseEnum;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.PageUtil;
import com.yami.shop.dao.ActivityReceiveRecordMapper;
import com.yami.shop.mystery.common.model.ActivityPresell;
import com.yami.shop.mystery.common.model.MysteryBox;
import com.yami.shop.mystery.common.model.MysteryBoxOrder;
import com.yami.shop.mystery.common.model.MysteryBoxUserArk;
import com.yami.shop.mystery.common.service.*;
import com.yami.shop.service.*;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class ActivityReceiveRecordServiceImpl extends ServiceImpl<ActivityReceiveRecordMapper, ActivityReceiveRecord> implements ActivityReceiveRecordService {

    @Autowired
    private ProductService productService;

    @Autowired
    private ActivityPresellService activityPresellService;

    @Autowired
    private BusinessNftService businessNftService;

    @Autowired
    private ActivityReceiveRecordMapper activityReceiveRecordMapper;

    @Autowired
    private ApplicationEventPublisher eventPublisher;

    @Autowired
    private ChannelUserRelationRecordService channelUserRelationRecordService;

    @Autowired
    private ProductService prodService;

    @Autowired
    private MysteryBoxService mysteryBoxService;

    @Autowired
    private MysteryBoxUserArkService mysteryBoxUserArkService;

    @Autowired
    private MysteryBoxOpenRecordService mysteryBoxOpenRecordService;

    @Autowired
    private ShopDetailService shopDetailService;

    @Autowired
    private SkuStockLockService skuStockLockService;

    @Autowired
    private SkuService skuService;



    @Override
    @Transactional(rollbackFor = Exception.class)
    public void receive(ActivityReceiveRecord activityReceiveRecord) {
        activityReceiveRecord.setId(IdUtil.getSnowflakeNextId());
        // 校验是否领取过
        LambdaQueryWrapper<ActivityReceiveRecord> eq = new LambdaQueryWrapper<ActivityReceiveRecord>()
                .eq(ActivityReceiveRecord::getProdId, activityReceiveRecord.getProdId())
                .eq(ActivityReceiveRecord::getUserId, activityReceiveRecord.getUserId())
                .eq(ActivityReceiveRecord::getActivityId,activityReceiveRecord.getActivityId());
        List<ActivityReceiveRecord> receiveRecordList = list(eq);
        if(ObjectUtils.isNotEmpty(receiveRecordList)){
            throw new YamiShopBindException("该用户已领取过");
        }
        ActivityPresell byId = activityPresellService.getById(activityReceiveRecord.getActivityId());
        if(byId.getBlindType() == 0){
            Product productInfo = prodService.getProductInfo(Long.valueOf(activityReceiveRecord.getProdId()));
            // 是否拥有该商品链上地址
            Boolean hasDTCAddress = channelUserRelationRecordService.isHasDTCAddress(activityReceiveRecord.getUserId(), productInfo.getChain(), productInfo.getChannelCode());
            if(!hasDTCAddress){
                throw new YamiShopBindException("该用户未创建链上地址");
            }
            // 查询商品是否有库存
            List<SkuStockLockDTO> skuStockLocks = new ArrayList<>();
            List<Sku> skulist = skuService.listSkuAndSkuStock(Long.valueOf(activityReceiveRecord.getProdId()));
            SkuStockLockDTO skuStockLockDTO = new SkuStockLockDTO(Long.valueOf(activityReceiveRecord.getProdId()), skulist.get(0).getSkuId(), activityReceiveRecord.getId().toString(), byId.getPurchaseNum());
            skuStockLocks.add(skuStockLockDTO);
            ServerResponseEntity<?> lockStockResponse = skuStockLockService.lock(skuStockLocks,null);
            if (Objects.equals(ResponseEnum.NOT_STOCK.value(), lockStockResponse.getCode())) {
                throw new YamiShopBindException(I18nMessage.getMessage("yami.insufficient.inventory"));
            }

            List<EsProdUpdateVO> prodList = new ArrayList<>();
            Set<Long> prodIds = new HashSet<>();
            EsProdUpdateVO esProdUpdateVO = new EsProdUpdateVO();
            esProdUpdateVO.setProdId(Long.valueOf(activityReceiveRecord.getProdId()));
            esProdUpdateVO.setCount(byId.getPurchaseNum());
            esProdUpdateVO.setType(0);
            prodList.add(esProdUpdateVO);
            prodIds.add(Long.valueOf(activityReceiveRecord.getProdId()));
            // 更新es中的商品库存
            eventPublisher.publishEvent(new EsProductUpdateEvent(null, new ArrayList<>(prodIds), EsOperationType.UPDATE_BATCH));
            // 更新es中的商品库存--更新失败打印日志，优先保证订单流程没问题
            eventPublisher.publishEvent(new EsProductUpdateEvent(prodList, EsOperationType.UPDATE_ORDER_STOCK_NUM_BATCH));
            activityReceiveRecord.setReceiveNum(byId.getPurchaseNum());
            activityReceiveRecord.setStatus(0);
            activityReceiveRecord.setCreateTime(new Date());
            activityReceiveRecordMapper.insert(activityReceiveRecord);
            BusinessNft businessNft = new BusinessNft();
            businessNft.setNum(byId.getPurchaseNum());
            businessNft.setBusinessType(4);
            businessNft.setUserId(activityReceiveRecord.getUserId());
            businessNft.setProdId(String.valueOf(activityReceiveRecord.getProdId()));
            businessNft.setStatus(0);
            businessNft.setCreateTime(new Date());
            businessNft.setOutId(String.valueOf(activityReceiveRecord.getId()));
            businessNft.setProdName(productInfo.getProdName());
            businessNftService.save(businessNft);
        }
        // 如果是盲盒
        else{
            MysteryBox detail = mysteryBoxService.detail((long) activityReceiveRecord.getProdId());
            // 通过店铺ID 获取 渠道ID
//            ShopDetail shopDetailByShopId = shopDetailService.getShopDetailByShopId(detail.getShopId());
            // 是否拥有该商品链上地址
//            Boolean hasDTCAddress = channelUserRelationRecordService.isHasDTCAddress(activityReceiveRecord.getUserId(), detail.getChain(), shopDetailByShopId.getChannelCode());
//            if(!hasDTCAddress){
//                throw new YamiShopBindException("该用户未创建链上地址");
//            }
            if (detail.getBoxSku() == null || detail.getBoxSku().getStocks() <= 0 || detail.getBoxSku().getStocks() - byId.getPurchaseNum() < 0) {
                // 库存不足
                throw new YamiShopBindException("库存不足，请重试！");
            }
            if (!mysteryBoxService.decrMysteryBoxSkuStocks((long) activityReceiveRecord.getProdId(), byId.getPurchaseNum())) {
                throw new YamiShopBindException("更新盲盒库存失败！");
            }
            // 增加开盒次数
            MysteryBoxUserArk mysteryBoxUserArk = mysteryBoxUserArkService.getOne(Wrappers.lambdaQuery(MysteryBoxUserArk.class).eq(MysteryBoxUserArk::getUid, activityReceiveRecord.getUserId()).eq(MysteryBoxUserArk::getBid, (long) activityReceiveRecord.getProdId()));
            if (ObjectUtil.isEmpty(mysteryBoxUserArk)) {
                MysteryBoxUserArk userArk = new MysteryBoxUserArk();
                userArk.setUid(activityReceiveRecord.getUserId());
                userArk.setBid((long) activityReceiveRecord.getProdId());
                userArk.setCount(byId.getPurchaseNum().longValue());
                userArk.setStatus("0");
                mysteryBoxUserArkService.save(userArk);
            } else {
                mysteryBoxUserArkService.update(Wrappers.lambdaUpdate(MysteryBoxUserArk.class).setSql("count = count + " + byId.getPurchaseNum() + ",status = 0").eq(MysteryBoxUserArk::getUid, activityReceiveRecord.getUserId()).eq(MysteryBoxUserArk::getBid, (long) activityReceiveRecord.getProdId()));
            }
            // 生成默认开合记录
            MysteryBoxOrder mysteryBoxOrder = new MysteryBoxOrder();
            mysteryBoxOrder.setMysteryBoxId((long) activityReceiveRecord.getProdId());
            mysteryBoxOrder.setUserId(activityReceiveRecord.getUserId());
            mysteryBoxOrder.setProdCount(byId.getPurchaseNum().longValue());
            mysteryBoxOpenRecordService.initMysteryBoxOpenRecord(mysteryBoxOrder);
            activityReceiveRecord.setReceiveNum(byId.getPurchaseNum());
            activityReceiveRecord.setStatus(0);
            activityReceiveRecord.setCreateTime(new Date());
            activityReceiveRecordMapper.insert(activityReceiveRecord);
            // 盲盒库存
            eventPublisher.publishEvent(new MysteryBoxSoldOutEvent((long) activityReceiveRecord.getProdId()));
        }
    }

    @Override
    public PageVO<ActivityReceiveRecord> pageListbyUserId(PageDTO pageDTO, String userId ,String shopId) {
        LambdaQueryWrapper<ActivityReceiveRecord> activityReceiveRecordLambdaQueryWrapper = new LambdaQueryWrapper<ActivityReceiveRecord>().eq(ActivityReceiveRecord::getUserId, userId).eq(ActivityReceiveRecord::getShopId, shopId).orderByDesc(ActivityReceiveRecord::getCreateTime);
        PageVO<ActivityReceiveRecord> pageVO = PageUtil.doPage(pageDTO, () -> activityReceiveRecordMapper.selectList(activityReceiveRecordLambdaQueryWrapper));
        if(ObjectUtils.isNotEmpty(pageVO.getList())){
            for(ActivityReceiveRecord activityReceiveRecord : pageVO.getList()){
                ActivityPresell activityPresell = activityPresellService.getById(activityReceiveRecord.getActivityId());
                if(activityPresell.getBlindType() == 0){
                    Product byId = productService.getById(activityReceiveRecord.getProdId());
                    activityReceiveRecord.setProdName(byId.getProdName());
                    activityReceiveRecord.setPic(byId.getPic());
                }else {
                    MysteryBox detail = mysteryBoxService.getById(activityReceiveRecord.getProdId());
                    activityReceiveRecord.setProdName(detail.getBoxName());
                    activityReceiveRecord.setPic(detail.getPic());
                }
            }
        }
        return pageVO;
    }

    @Override
    public PageVO<ActivityReceiveRecord> zeroPage(PageDTO pageDTO, String prodName, String userName, String userMobile, String status, Long shopId) {
        PageVO<ActivityReceiveRecord> pageVO = PageUtil.doPage(pageDTO, () -> activityReceiveRecordMapper.getPageList(prodName,userName,userMobile,status,shopId));
        return pageVO;
    }

}
